package com.bandit.provider.impl;

import com.bandit.config.RpcServiceConfig;
import com.bandit.emums.RpcExceptionMessageEnum;
import com.bandit.exception.RpcException;
import com.bandit.extension.ExtensionLoader;
import com.bandit.provider.ServiceProvider;
import com.bandit.registry.ServiceRegistry;
import com.bandit.remoting.transport.socket.RpcSocketServer;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Bandit
 * @create 2022/2/23 15:49
 */
@Slf4j
public class ZKServiceProviderImpl implements ServiceProvider {

    /**
     * key: rpc service name(interface name + version + group)
     * value: service object
     */
    private final Map<String,Object> serviceMap;
    private final Set<String> registeredService;
    private final ServiceRegistry serviceRegistry;


    public ZKServiceProviderImpl(){
        serviceMap = new ConcurrentHashMap<>();
        registeredService = ConcurrentHashMap.newKeySet();
        serviceRegistry = ExtensionLoader.getExtensionLoader(ServiceRegistry.class).getExtension("zk");
    }

    @Override
    public void addService(RpcServiceConfig rpcServiceConfig) {
        String rpcServiceName = rpcServiceConfig.getRpcServiceName();//服务的 interface name + version + group
        if (registeredService.contains(rpcServiceName)) {
            return;
        }
        serviceMap.put(rpcServiceName,rpcServiceConfig.getService());
        registeredService.add(rpcServiceName);
        log.info("Add service: {} and interfaces:{}",rpcServiceName,rpcServiceConfig.getService().getClass().getInterfaces());
    }

    @Override
    public Object getService(String rpcServiceName) {
        Object service = serviceMap.get(rpcServiceName);
        if (service==null){
            throw new RpcException(RpcExceptionMessageEnum.SERVICE_CAN_NOT_BE_FOUND);
        }
        return service;
    }

    @Override
    public void publishService(RpcServiceConfig rpcServiceConfig) {
        try {
            String hostAddress = InetAddress.getLocalHost().getHostAddress();
            addService(rpcServiceConfig);
            serviceRegistry.registerService(rpcServiceConfig.getRpcServiceName(),new InetSocketAddress(hostAddress, RpcSocketServer.PORT));
        } catch (UnknownHostException e) {
            log.error("occur exception when getHostAddress", e);
        }
    }
}
